#include "StdAfx.h"
#include "Utility.h"
#include "CustomCheckBox.h"

#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;

IMPLEMENT_DYNAMIC(CCustomCheckBox, CButton)

CCustomCheckBox::CCustomCheckBox(void)
{
	//common Parameter
	m_nState = CBX_UNCHECKED_NORMAL;
	m_bMouseDowned = m_bChecked = false;

	//String and Font Parameter
	m_strText=_T("");
	m_nFontSize = 8;
	m_nFontStyle = FontStyleRegular;
	m_enFontUnit = UnitPoint;
	m_strTextFormat = NULL;
	m_pFontFamily = NULL;
	m_pFontBrush = NULL;
	m_pFont = NULL;

	//Image and Handle Parameter
	m_hBgDC = m_hDrawDC = NULL;
	m_hPParentWnd = m_hParentWnd = NULL;
	for(int i = 0; i < 6; ++i)
		m_pImg[i] = NULL;	
}

CCustomCheckBox::~CCustomCheckBox(void)
{
	if(m_pFont != NULL){ delete m_pFont;  m_pFont = NULL; }
	if(m_pFontBrush != NULL){ delete m_pFontBrush;  m_pFontBrush = NULL; }
	if(m_pFontFamily != NULL){ delete m_pFontFamily;  m_pFontFamily = NULL; }
	if(m_strTextFormat != NULL){ delete m_strTextFormat;  m_strTextFormat = NULL; }	

	for(int i = 0; i < 6; ++i)
		if ( m_pImg[i] )
			delete m_pImg[i];
}

/*********************************************************************************************************************/
/*********************************************************************************************************************/
//Common Setting
/*********************************************************************************************************************/
/*********************************************************************************************************************/
BOOL CCustomCheckBox::GetChecked()
{
	if(m_nState != CBX_CHECKED_DISABLED && m_nState != CBX_UNCHECKED_DISABLED)
    	return (BOOL)m_bChecked;
	else
		return false;
}

void CCustomCheckBox::SetChecked(bool bChecked)
{
	if(m_nState != CBX_CHECKED_DISABLED && m_nState != CBX_UNCHECKED_DISABLED)
	{
		if(bChecked){ SetState(CBX_CHECKED_NORMAL);  m_bChecked = true; }
		else        { SetState(CBX_UNCHECKED_NORMAL);  m_bChecked = false; }
	}
}

void CCustomCheckBox::SetState(int nState)
{
	if(m_nState != nState){ m_nState = nState;  if(m_hDrawDC) Invalidate(); }
}

BOOL CCustomCheckBox::EnableWindow(BOOL bEnable)
{
	if(bEnable)
	{
		if (m_bChecked)  SetState(CBX_CHECKED_NORMAL);
		else             SetState(CBX_UNCHECKED_NORMAL);
	}
	else
	{
		if (m_bChecked)  SetState(CBX_CHECKED_DISABLED);
		else             SetState(CBX_UNCHECKED_DISABLED);
	}

	return CButton::EnableWindow(bEnable);
}

void CCustomCheckBox::Initialize(HWND hPParentWnd, HWND hParentWnd, HDC hBgDC, HDC hDrawDC, int nParentx, int nParenty)
{
	m_hPParentWnd = hPParentWnd;
	m_hParentWnd = hParentWnd;

	m_hBgDC = hBgDC;
	m_hDrawDC = hDrawDC;

	::GetWindowRect(m_hPParentWnd, m_rtPPRect);
	::GetWindowRect(m_hParentWnd, m_rtPRect);

	GetWindowRect(&m_rtRect);
	m_rtRect.OffsetRect(+nParentx, +nParenty);
	m_rtRect.OffsetRect(-m_rtPRect.left, -m_rtPRect.top);
}

/*********************************************************************************************************************/
/*********************************************************************************************************************/
//Image Setting
/*********************************************************************************************************************/
/*********************************************************************************************************************/
void CCustomCheckBox::SetImage(UINT nCheckDis, UINT nCheck, UINT nCheckHover, UINT nUncheckDis, UINT nUncheck, UINT nUncheckHover)
{
	CUtility::ImageFromIDResource(nCheckDis, _T("PNG"), m_pImg[0]);
	CUtility::ImageFromIDResource(nCheck, _T("PNG"), m_pImg[1]);
	CUtility::ImageFromIDResource(nCheckHover, _T("PNG"), m_pImg[2]);
	CUtility::ImageFromIDResource(nUncheckDis, _T("PNG"), m_pImg[3]);
	CUtility::ImageFromIDResource(nUncheck, _T("PNG"), m_pImg[4]);
	CUtility::ImageFromIDResource(nUncheckHover, _T("PNG"), m_pImg[5]);
}

/*********************************************************************************************************************/
/*********************************************************************************************************************/
//String Font Setting
/*********************************************************************************************************************/
/*********************************************************************************************************************/
void CCustomCheckBox::SetWindowTextW(LPCTSTR lpszString)
{
	CButton::SetWindowTextW(lpszString);
	Invalidate();
}

void CCustomCheckBox::SetFontSize(int nSize)
{
	if(nSize > 0)
		m_nFontSize = nSize;
}

void CCustomCheckBox::SetFontStyle(UINT nStyle)
{
	if(nStyle >= 0)
		m_nFontStyle = nStyle;
}

void CCustomCheckBox::SetFontColor(int nR, int nG, int nB)
{
	if(m_pFontBrush!=NULL){ delete m_pFontBrush;  m_pFontBrush = NULL; }
	m_pFontBrush = new SolidBrush(Color(247, nR, nG, nB));	

}
void CCustomCheckBox::SetFontFamily(CString strFontFamilyName)
{
	if(!strFontFamilyName.IsEmpty())
	{
		if(m_pFontFamily!=NULL){ delete m_pFontFamily;  m_pFontFamily=NULL; }
		m_pFontFamily = new FontFamily(strFontFamilyName);
	}
}

void CCustomCheckBox::CreateFont()
{
	//----------------------new FontFamily
	if(m_pFontFamily == NULL)
		m_pFontFamily = new FontFamily(L"Arial");
	if(FontFamilyNotFound == m_pFontFamily->GetLastStatus())
	{
		if (this->m_hWnd)
		{
			CFont *pCurFont = this->GetFont();  LOGFONT LgFong;  pCurFont->GetLogFont(&LgFong);
			if(m_pFontFamily){ delete m_pFontFamily;  m_pFontFamily = NULL;  m_pFontFamily = new FontFamily(LgFong.lfFaceName); }
		}
	}
	
	//----------------------new Font
	if(m_pFont == NULL)
		m_pFont = new Gdiplus::Font(m_pFontFamily,(Gdiplus::REAL)m_nFontSize, m_nFontStyle, m_enFontUnit);

	//----------------------new StringFormat
	if(m_strTextFormat == NULL)
	{
		m_strTextFormat = new StringFormat;
		m_strTextFormat->SetAlignment(StringAlignmentNear);
		m_strTextFormat->SetLineAlignment(StringAlignmentNear);
		m_strTextFormat->SetTrimming(StringTrimmingEllipsisCharacter);
	}

	//----------------------new FontBrush
	if (m_pFontBrush == NULL)
		m_pFontBrush = new SolidBrush(Color(247, 5, 5, 5));	
}

/*********************************************************************************************************************/
/*********************************************************************************************************************/
//UI Drawing
/*********************************************************************************************************************/
/*********************************************************************************************************************/
void CCustomCheckBox::DrawItem(LPDRAWITEMSTRUCT di)
{
	DrawUI();
}

void CCustomCheckBox::DrawUI()
{
	BitBlt(m_hDrawDC, m_rtRect.left, m_rtRect.top, m_rtRect.Width(), m_rtRect.Height(), m_hBgDC, m_rtRect.left, m_rtRect.top, SRCCOPY);

	Graphics graphics( m_hDrawDC );
	Gdiplus::REAL width = (Gdiplus::REAL)m_pImg[m_nState]->GetWidth();
	Gdiplus::REAL height =  (Gdiplus::REAL)m_pImg[m_nState]->GetHeight();
	graphics.DrawImage(m_pImg[m_nState], (Gdiplus::REAL)m_rtRect.left, (Gdiplus::REAL)m_rtRect.top, width, height);

	GetWindowText(m_strText);
	if(!m_strText.IsEmpty())
	{
		CreateFont();
		graphics.DrawString(m_strText.GetBuffer(), -1, m_pFont, 
			                RectF((Gdiplus::REAL)m_rtRect.left + width + 3,    (Gdiplus::REAL)m_rtRect.top,
			                      (Gdiplus::REAL)m_rtRect.Width() - width - 3, (Gdiplus::REAL)m_rtRect.Height()),
			                m_strTextFormat, m_pFontBrush);
	}

	CUtility::UpdateWindow(m_hPParentWnd, m_hDrawDC, m_rtPPRect);
}

BOOL CCustomCheckBox::ShowWindow(int nCmdShow)
{
	switch(nCmdShow)
	{
	case SW_SHOW:
		Invalidate();
		break;
	case SW_HIDE:
		BitBlt(m_hDrawDC, m_rtRect.left, m_rtRect.top, m_rtRect.Width(), m_rtRect.Height(), m_hBgDC, m_rtRect.left, m_rtRect.top, SRCCOPY);
		CUtility::UpdateWindow(m_hPParentWnd, m_hDrawDC, m_rtPPRect);
		break;
	default:
		break;
	}

	return CButton::ShowWindow(nCmdShow);
}

/*********************************************************************************************************************/
/*********************************************************************************************************************/
//UI Message
/*********************************************************************************************************************/
/*********************************************************************************************************************/
BEGIN_MESSAGE_MAP(CCustomCheckBox, CButton)
	ON_WM_DRAWITEM()
	ON_WM_MOUSEMOVE()
	ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
	ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
	ON_WM_ERASEBKGND()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
void CCustomCheckBox::PreSubclassWindow()
{
	// TODO: Add your specialized code here and/or call the base class
	if(!IsWindowEnabled())
		m_nState = CBX_UNCHECKED_DISABLED;

    ModifyStyle(0, BS_OWNERDRAW);
	CButton::PreSubclassWindow();
}

BOOL CCustomCheckBox::OnEraseBkgnd(CDC* pDC)
{
	return TRUE;
}

//-------------------------------------------------
//-------------------------------------------------Mouse movement
void CCustomCheckBox::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	TRACKMOUSEEVENT tme;
	tme.cbSize = sizeof(tme);
	tme.hwndTrack = m_hWnd;
	tme.dwFlags = TME_LEAVE|TME_HOVER;
	tme.dwHoverTime = 1;
	_TrackMouseEvent(&tme);

	CButton::OnMouseMove(nFlags, point);
}

LRESULT CCustomCheckBox::OnMouseLeave(WPARAM wparam, LPARAM lparam)
{
	if(m_nState != CBX_CHECKED_DISABLED && m_nState != CBX_UNCHECKED_DISABLED)
	{
		if (m_bChecked)  SetState(CBX_CHECKED_NORMAL);
		else             SetState(CBX_UNCHECKED_NORMAL);
	}
	return 0;
}

LRESULT CCustomCheckBox::OnMouseHover(WPARAM wparam, LPARAM lparam) 
{
	if(m_nState != CBX_CHECKED_DISABLED && m_nState != CBX_UNCHECKED_DISABLED)
	{
		if (m_bChecked)  SetState(CBX_CHECKED_HOVERED);
		else             SetState(CBX_UNCHECKED_HOVERED);
	}
	return 0;
}

//-------------------------------------------------
//-------------------------------------------------Mouse LButton
void CCustomCheckBox::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	if(m_bMouseDowned)
	{
		CRect rect(m_rtRect);
		rect.OffsetRect( -m_rtRect.left, -m_rtRect.top);
		if(::PtInRect(rect, point))
		{
			if(m_bChecked) { SetState(CBX_UNCHECKED_HOVERED);  m_bChecked = false; }
			else           { SetState(CBX_CHECKED_HOVERED);   m_bChecked = true; }
		}
		m_bMouseDowned = false;
	}
	
	CButton::OnLButtonUp(nFlags, point);
}

void CCustomCheckBox::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	if(m_nState != CBX_CHECKED_DISABLED && m_nState != CBX_UNCHECKED_DISABLED)
		m_bMouseDowned = true;

	CButton::OnLButtonDown(nFlags, point);
}
